
package com.movisol.messenger.views;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager.LayoutParams;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ViewAnimator;

import com.movisol.messenger.R;
import com.movisol.messenger.controllers.MessengerController;
import com.movisol.messenger.views.controls.ContactRow;
import com.movisol.messenger.views.controls.EmailTab;
import com.movisol.messengercommunicator.data.Contact;
import com.movisol.messengercommunicator.data.Conversation;
import com.movisol.messengercommunicator.helper.MessengerCommunicatorHelper;
import com.movisol.messengercommunicator.ilisteners.IConversationsListLoaded;
import com.movisol.messengerprofileservice.data.Friend;
import com.movisol.messengerprofileservice.data.UserProfile;
import com.movisol.messengerprofileservice.events.DataLoadedEvent;
import com.movisol.messengerprofileservice.helpers.MessengerProfileHelper;
import com.movisol.messengerprofileservice.interfaces.errorcodes.FriendStatus;
import com.movisol.messengerprofileservice.listeners.IFriendsDataLoadedListener;
import com.movisol.tools.HelperUtils;

/**
 * Main page is the main Activity of the app. It handle the login process and
 * the process started after that.
 * 
 * @author Antonio Santiago
 */
public class MainPage extends Activity implements IFriendsDataLoadedListener, IConversationsListLoaded, OnClickListener
{

	private final MessengerController mc = MessengerController.getInstance();

	private Context context;

	private LinearLayout ll;

	private Button imBtnProfile;

	private Button imBtnConversations;

	private boolean newRun = true; // Helps us to determinate if it this is a
									// new run

	private AlertDialog ad = null;

	private EmailTab addNewContact = null;

	private ViewAnimator viewAnimatorBottomBar = null;

	private EditText searchBar = null;

	private boolean searchingContacts = false;

	private List<Friend> approvedFriendList;

	private List<Contact> contactsToChatWith;

	private ContactRow selectedContactRow;

	private boolean creatingGroupChat = false;

	private Button createGroupChatButton = null;

	private Handler timer;

	private Runnable r = null;

	private boolean timerStarted = false;

	private static final long WAIT_TIME_TO_REQUEST = 20000;

	// private HashMap<String, Friend> friends;

	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.mainpage);
		getWindow().setFormat(PixelFormat.RGBA_8888);
		getWindow().addFlags(LayoutParams.FLAG_DITHER);
		context = getApplicationContext();
		mc.setContext(context);

	}

	@Override
	protected void onStart()
	{
		super.onStart();

		if (!mc.isLoaded())
		{
			newRun = true;
			Intent login = new Intent(this, Login.class);
			startActivityForResult(login, 1);
		} else
		{
			mc.setCurrentPage(MessengerController.MAIN_PAGE);
			if (newRun)
			{
				mc.pc.addFriendsDataLoadedListener(this);
				mc.pc.addFriendsDataUpdatedListener(this);

				initializeGUI();

				mc.cc.addConversationListLoadedListener(this);
				mc.loadConversationsList();

				if (mc.pc.getFriends() == null
						|| (mc.pc.getFriends() != null && mc.pc.getFriends().getFriendList().size() == 0))
					mc.loadFriendList();
				else
				{
					showApprovedContactList();
					timerStart();
				}
			}
		}
	}

	@Override
	protected void onDestroy()
	{
		super.onDestroy();
		mc.pc.removeFriendsDataLoadedListener(this);
		mc.pc.removeFriendsDataUpdatedListener(this);

		mc.setCurrentPage(0);
		ll.removeAllViews();

		if (timer != null)
			timer.removeCallbacks(r, null);
		timer = null;
		r = null;
		timerStarted = false;
	}

	@Override
	protected void onStop()
	{
		super.onStop();
		if (searchingContacts)
			hideContactSearchBar();
		else if (creatingGroupChat)
			hideGroupChatButton();
		else
			resetContactRows();
	}

	@Override
	protected void onPause()
	{
		super.onPause();
		if (mc != null && mc.cc != null)
			mc.cc.removeConversationListLoadedListener(this);

		if (timer != null)
			timer.removeCallbacks(r, null);
		timerStarted = false;
	}

	@Override
	protected void onResume()
	{
		super.onResume();
		if (timer != null && !timerStarted)
			timer.sendEmptyMessageDelayed(0, WAIT_TIME_TO_REQUEST);
		//
		// if (selectedContactRow != null)
		// selectedContactRow.getContactButton().getBackground().mutate().setAlpha(255);
	}

	private void initializeGUI()
	{

		ll = (LinearLayout) findViewById(R.id.layoutContactsMp);

		imBtnProfile = (Button) findViewById(R.id.imBtnProfile);
		imBtnProfile.setOnClickListener(this);

		imBtnConversations = (Button) findViewById(R.id.imBtnConversations);
		imBtnConversations.setOnClickListener(this);

		viewAnimatorBottomBar = (ViewAnimator) findViewById(R.id.viewAnimBottomBar);

		createGroupChatButton = new Button(context);
		createGroupChatButton.setTag("createGroupChatButton");
		createGroupChatButton.setText("Select contacts and press");
		createGroupChatButton.setOnClickListener(this);

		// friends = new HashMap<String, Friend>();
	}

	public void timerStart()
	{

		if (!timerStarted)
		{
			timerStarted = true;
			timer = new Handler()
			{

				@Override
				public void handleMessage(android.os.Message msg)
				{
					super.handleMessage(msg);
					mc.loadFriendList();
				}
			};
		}
	}

	@Override
	public void friendsDataLoaded(DataLoadedEvent evt)
	{
		mc.setDataLoaded(true);
		showApprovedContactList();
		timerStart();

	}


	private void showApprovedContactList()
	{
		new approvedContactListAsyncShow().execute(this);
	}

	private class approvedContactListAsyncShow extends AsyncTask<OnClickListener, Void, Void>
	{

		boolean update = false;

		@Override
		protected Void doInBackground(OnClickListener... params)
		{

			approvedFriendList = MessengerProfileHelper.filterFriends(mc.pc.getFriends().getFriendList(),
					FriendStatus.APPROVED);

			if (approvedFriendList.size() != mc.getApprovedContactList().size())
			{
				for (Friend friend : approvedFriendList)
				{
					ContactRow newContact = new ContactRow(context, friend);
					newContact.setOnClickListener(params[0]);
					newContact.getContactButton().setOnClickListener(params[0]);
					mc.getApprovedContactList().add(newContact);
				}
				update = true;
			}
			if (ll != null && ll.getChildCount() == 0)
				update = true;

			return null;
		}

		@Override
		protected void onPostExecute(Void result)
		{
			super.onPostExecute(result);
			if (update)
			{
				for (ContactRow contactRow : mc.getApprovedContactList())
				{
					ll.addView(contactRow);
				}
				update = false;
			}
			refreshApprovedContactList();
		}

	}


	public void refreshApprovedContactList()
	{
		new approvedContactListAsyncRefresh().execute(this);
	}

	private class approvedContactListAsyncRefresh extends AsyncTask<OnClickListener, Void, Void>
	{

		List<Integer> insertPositions = new ArrayList<Integer>();

		List<Integer> deletePositions = new ArrayList<Integer>();

		List<ContactRow> contactsToRefresh = new ArrayList<ContactRow>();

		List<ContactRow> contactsToDelete = new ArrayList<ContactRow>();

		@Override
		protected Void doInBackground(OnClickListener... params)
		{

			int insertPositionCounter = 0;
			int deletePositionCounter = 0;

			if (approvedFriendList == null)
				approvedFriendList = MessengerProfileHelper.filterFriends(mc.pc.getFriends().getFriendList(),
						FriendStatus.APPROVED);

			// contactsToRefresh = new ArrayList<ContactRow>();

			for (Friend friend : approvedFriendList)
			{
				insertPositionCounter = 0;
				for (ContactRow contact : mc.getApprovedContactList())
				{
					if (contact.getFriend().getUserProfile().getUserId().equals(friend.getUserProfile().getUserId())
							&& contact.getFriend().hashCode() != friend.hashCode())
					{
						ContactRow newContact = new ContactRow(context, friend);
						newContact.setOnClickListener(params[0]);
						newContact.getContactButton().setOnClickListener(params[0]);
						insertPositions.add(insertPositionCounter);
						deletePositions.add(deletePositionCounter);
						contactsToRefresh.add(newContact);
						contactsToDelete.add(contact);
					}
					insertPositionCounter++;
				}
				deletePositionCounter++;
			}

			return null;

		}

		@Override
		protected void onPostExecute(Void result)
		{
			super.onPostExecute(result);
			int c = 0;

			for (ContactRow contact : contactsToDelete)
			{
				ll.removeView(contact);
				mc.getApprovedContactList().remove(contact);
			}

			for (ContactRow contact : contactsToRefresh)
			{
				ll.addView(contact, insertPositions.get(c));
				mc.getApprovedContactList().add(insertPositions.get(c), contact);
				c++;
			}
			if (timer != null)
				timer.sendEmptyMessageDelayed(0, WAIT_TIME_TO_REQUEST);
		}

	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data)
	{
		super.onActivityResult(requestCode, resultCode, data);

		switch (requestCode)
		{
		case 1:
			if (resultCode == -1)
			{
				finish();
			}
			break;

		case 2:
			if (resultCode == -1)
			{
				finish();
			} else
				newRun = false;
			break;

		case 3:
			newRun = false;
			break;
		case 4:
			newRun = false;
			break;
		case 5:
			newRun = false;
			break;
		}

	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu)
	{

		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.mainpage_menu, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item)
	{
		// Handle item selection
		switch (item.getItemId())
		{
		case R.id.add_contact:
			showAddContact();
			return true;
		case R.id.search:
			if (!searchingContacts)
			{
				if (creatingGroupChat)
					hideGroupChatButton();
				showContactSearchBar();
			} else
				hideContactSearchBar();
			return true;
		case R.id.waiting_friends:
			showWaitingListPage();
			return true;
		case R.id.group_chat:
			if (!creatingGroupChat)
			{
				if (searchingContacts)
					hideContactSearchBar();
				showGroupChatButton();
			} else
				hideGroupChatButton();
			return true;
		default:
			return super.onOptionsItemSelected(item);
		}
	}

	private void hideGroupChatButton()
	{

		viewAnimatorBottomBar.showPrevious();
		viewAnimatorBottomBar.removeViewAt(1);

		resetContactRows();

		creatingGroupChat = false;
	}

	private void resetContactRows()
	{
		if (mc.getApprovedContactList() != null && mc.getApprovedContactList().size() > 0)
			for (ContactRow approved : mc.getApprovedContactList())
			{
				approved.getContactButton().setVisibility(View.VISIBLE);
				approved.setSelected(false);
			}
	}

	private void showGroupChatButton()
	{
		creatingGroupChat = true;
		contactsToChatWith = new ArrayList<Contact>();

		for (ContactRow approved : mc.getApprovedContactList())
			approved.getContactButton().setVisibility(View.INVISIBLE);

		viewAnimatorBottomBar.addView(createGroupChatButton);
		viewAnimatorBottomBar.showNext();

	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event)
	{

		if ((keyCode == KeyEvent.KEYCODE_BACK))
		{
			if (searchingContacts)
			{
				hideContactSearchBar();
				return false;
			}
			if (creatingGroupChat)
			{
				hideGroupChatButton();
				return false;
			}
		}

		return super.onKeyDown(keyCode, event);
	}

	private void showWaitingListPage()
	{
		Intent waitingListPageIntent = new Intent(this, WaitingListPage.class);
		startActivityForResult(waitingListPageIntent, 3);
	}

	private void showAddContact()
	{

		addNewContact = new EmailTab(context, "Send", "Cancel");
		addNewContact.getBtOkEmail().setOnClickListener(this);
		addNewContact.getBtCancelEmail().setOnClickListener(this);

		ad = new AlertDialog.Builder(this).setTitle("Send invitation to:").setView(addNewContact).show();
	}

	private void showContactSearchBar()
	{
		searchBar = new EditText(context);
		// Allow just one line
		searchBar.setInputType(InputType.TYPE_TEXT_FLAG_IME_MULTI_LINE);

		TextWatcher tWatcher = new TextWatcher()
		{

			@Override
			public void onTextChanged(CharSequence s, int start, int before, int count)
			{
				if (s.toString().equalsIgnoreCase(""))
				{
					for (ContactRow approved : mc.getApprovedContactList())
						approved.setVisibility(View.VISIBLE);
				} else
					for (ContactRow approved : mc.getApprovedContactList())
					{
						UserProfile up = approved.getFriend().getUserProfile();

						// Search by Name or Email
						if (up.getCalculatedNickName().toLowerCase().contains(s.toString().toLowerCase())
								|| up.getEmail().toLowerCase().contains(s.toString().toLowerCase()))
							approved.setVisibility(View.VISIBLE);
						else
							approved.setVisibility(View.GONE);

					}
			}

			@Override
			public void beforeTextChanged(CharSequence s, int start, int count, int after)
			{

			}

			@Override
			public void afterTextChanged(Editable s)
			{

			}
		};

		searchBar.addTextChangedListener(tWatcher);
		viewAnimatorBottomBar.addView(searchBar);
		viewAnimatorBottomBar.showNext();
		searchingContacts = true;
		searchBar.requestFocus();
		InputMethodManager in = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
		in.showSoftInput(searchBar, InputMethodManager.SHOW_IMPLICIT);
	}

	private void hideContactSearchBar()
	{
		viewAnimatorBottomBar.showPrevious();
		viewAnimatorBottomBar.removeViewAt(1);
		searchingContacts = false;

		for (ContactRow approved : mc.getApprovedContactList())
			approved.setVisibility(View.VISIBLE);
	}

	/*Once the conversations are loaded, we must obtain the last conversation we had with the selected contactId
	 * If we have not had any conversation, the conversationId and lastMessage will be null*/
	// @Override
	public void findConversation()
	{

		Conversation conversation = new Conversation();
		conversation.setContacts(new ArrayList<Contact>());
		conversation.setContacts(contactsToChatWith);

		if (mc.cc.getConversationsList() != null)
			// Fetch into the conversations of the user
			for (Conversation conver : mc.cc.getConversationsList().getConversations())
			{
				int contactMatchs = 0;
				// Just search in the conversation that has the same number of
				// contact as the selected ones
				if (conver.getContacts().size() == contactsToChatWith.size())
				{
					for (Contact contact : conver.getContacts())
					{
						for (Contact contactToChat : contactsToChatWith)
							if (contact.getContactId().equals(contactToChat.getContactId()))
								contactMatchs++;
					}

					if (contactMatchs == contactsToChatWith.size())
					{
						conversation.setConversationId(conver.getConversationId());
						conversation.setLastMessage(conver.getLastMessage());
						conversation.setUri(conver.getUri());
						break;
					}
				}
			}

		mc.setCurrentConversation(conversation);

		// pc.getComManager().removeConversationListLoadedListener(this);

	}

	@Override
	public void onClick(View v)
	{

		switch (v.getId())
		{
		case R.id.imBtnProfile:
			Intent profileIntent = new Intent(this, ProfilePage.class);
			profileIntent.putExtra("me", true);
			startActivityForResult(profileIntent, 2);
			break;

		case R.id.btOkEmail:

			String email = addNewContact.getEdTxtEmail().getText().toString();

			if (!MessengerProfileHelper.isFriendAlreadyAdded(email, mc.pc.getFriends().getFriendList()))
			{
				if (MessengerProfileHelper.validateEmail(email))
				{
					addNewContact.hideErrorMessage();

					List<String> emailList = new ArrayList<String>();
					emailList.add(email);

					mc.addContact(emailList, true);
					ad.dismiss();
				} else
					addNewContact.showErrorMessage("Invalid Email");
			} else
				addNewContact.showErrorMessage("Friend already added");

			break;

		case R.id.btCancelEmail:
			ad.dismiss();
			break;

		case R.id.imBtnConversations:
			Intent conversationPageIntent = new Intent(this, Conversations.class);
			startActivityForResult(conversationPageIntent, 4);
			break;

		}

		/*If the view clicked is a ContactRow, it retrieves the userId associated to it, and loads the conversations*/
		if (v instanceof ContactRow)
		{
			if (creatingGroupChat)
			{
				selectedContactRow = (ContactRow) v;
				Contact contact = new Contact();
				contact.setContactId(selectedContactRow.getFriend().getUserProfile().getUserId());
				// TODO pa ver si va
				contact.setEmail(selectedContactRow.getFriend().getUserProfile().getEmail());
				contact.setName(selectedContactRow.getFriend().getUserProfile().getCalculatedNickName());

				if (((ContactRow) v).isSelected())
				{
					selectedContactRow.setSelected(false);
					contactsToChatWith.remove(contact);
				} else
				{
					selectedContactRow.setSelected(true);
					contactsToChatWith.add(contact);
				}

			} else
			{
				contactsToChatWith = new ArrayList<Contact>();
				selectedContactRow = (ContactRow) v;
				selectedContactRow.setSelected(true);
				Contact contact = new Contact();
				contact.setContactId(selectedContactRow.getFriend().getUserProfile().getUserId());
				// TODO prueba pa ver si cuela
				contact.setEmail(selectedContactRow.getFriend().getUserProfile().getEmail());
				contact.setName(selectedContactRow.getFriend().getUserProfile().getCalculatedNickName());
				contactsToChatWith.add(contact);
				findConversation();

				Intent chat = new Intent(this, Chat.class);
				startActivityForResult(chat, 5);
			}

		}

		if (v.getTag() != null && v.getTag().equals("contactProfileButton"))
		{
			selectedContactRow = ((ContactRow) v.getParent().getParent().getParent().getParent());

			// Trick to forces the button to redraw
			selectedContactRow.getContactButton().setBackgroundDrawable(null);
			selectedContactRow.getContactButton().setBackgroundResource(
					HelperUtils.getDrawableResource("ic_friend_profile_btn", context));
			selectedContactRow.getContactButton().getBackground().mutate().setAlpha(128);

			mc.pc.setTmpUserProfile(selectedContactRow.getFriend().getUserProfile());
			Intent profileIntent = new Intent(this, ProfilePage.class);
			startActivityForResult(profileIntent, 2);
			selectedContactRow.postDelayed(new Runnable()
			{

				@Override
				public void run()
				{
					selectedContactRow.getContactButton().getBackground().mutate().setAlpha(255);

				}
			}, 1000);

		}

		if (v.getTag() != null && v.getTag().equals("createGroupChatButton"))
		{
			if (contactsToChatWith.size() > 1)
			{
				findConversation();
				Intent chat = new Intent(this, Chat.class);
				startActivityForResult(chat, 5);
			}
		}
	}

	@Override
	public void conversationListLoaded(com.movisol.messengercommunicator.events.DataLoadedEvent evt)
	{

		String type = getIntent().getStringExtra("type");
		// mc.loadConversationsList(); // TODO QUITAR
		if (type != null)
		{
			if (type.equals("c-invRec"))
			{
				String sui = getIntent().getStringExtra("sui");
				Intent waitingListPageIntent = new Intent(this, WaitingListPage.class);
				waitingListPageIntent.putExtra("sui", sui);
				waitingListPageIntent.putExtra("type", "c-invRec");
				// waitingListPageIntent.putExtra("type", sn);
				startActivityForResult(waitingListPageIntent, 3);
			}

			if (type.equals("c-msgRec"))
			{
				String ci = getIntent().getStringExtra("ci");
				mc.setCurrentConversation(MessengerCommunicatorHelper.findConversationByConversationId(ci, mc.cc
						.getConversationsList().getConversations()));
				Intent chat = new Intent(this, Chat.class);
				startActivityForResult(chat, 5);
			}
		}
	}

}
